type MyReturnType<T extends (...args: any) => any> = T extends (
  ...args: any
) => infer R
  ? R
  : never;

// 使用 infer 假设 返回值类型是 R

/**
 * 内置 ReturnType
 */
const add = (value: boolean) => {
  if (value) {
    return 111;
  } else {
    return 222;
  }
};
const sum = () => {
  return 111;
};
type resultType1 = ReturnType<typeof add>;

type resultType2 = ReturnType<typeof sum>;

// type MyReturnType<T> = T是一个函数 ? 函数的返回值类型 : T
/**
 * 通过 extends 判断
 * T extends Function 表示 T 是不是一个函数
 * 函数的表示方法 Function 还有 (...args: any[]) => void
 */
type MyReturnType2<T> = T extends (...args: any[]) => infer R ? R : T;
// infer 是推断
// type FN = (...args: any[]) => void;

// 一.
type pt = PromiseType<Promise<string>>; // string

type PromiseType<T> = T extends Promise<infer K> ? K : T;

// 二. 如果Promise里面 还是一个 Promise 嵌套了多层。要拿到最近里面的Promise<T> 中的T。就要递归调用
type PType = PromiseProType<Promise<Promise<string>>>; // string
type PromiseProType<T> = T extends Promise<infer K> ? PromiseProType<K> : T;

// 三, 得到函数第一个参数的类型
type fa = FirstArg<(name: string, age: number) => void>; // string
// T 是 一个函数  函数的第一个参数 使用 infer 推断类型,
type FirstArg<T> = T extends (name: infer R, ...args: any[]) => any ? R : T;

// 四，得到数组每一项的类型
type TupleArrType = [string, number];
const Tu: TupleArrType = ["11", 0];
type ItemType1 = ArrayType<[string, number]>; // string | number;
// string[] 字符串数组，(infer R)[] 推断
type ArrayType<T> = T extends (infer R)[] ? R : T;
